package com.diyizu.youdianda.serviceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.diyizu.youdianda.common.R;
import com.diyizu.youdianda.entity.SysMenu;
import com.diyizu.youdianda.dto.SysMenuDto;
import com.diyizu.youdianda.entity.SysRoleMenu;
import com.diyizu.youdianda.mapper.SysMenuMapper;
import com.diyizu.youdianda.service.SysMenuService;
import com.diyizu.youdianda.service.SysRoleMenuService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    /*
     * 展示列表有分级，按照如下格式给予数据：
     * 一级：xx设置
     *     二级：xx管理
     *         三级：列表、添加、更新、删除
     * */
    @Override
    public List<SysMenuDto> DataList() {

        /*使用component路由名称作为分组依据*/
        //二级列表内容
        LambdaQueryWrapper<SysMenu> lqw2 = new LambdaQueryWrapper<>();
        lqw2.like(SysMenu::getComponent, "/");   //该级所有字段都会有/
        List<SysMenu> list2 = this.list(lqw2);

        //将二级列表放进去
        ArrayList<SysMenuDto> sysMenuDtos2 = new ArrayList<>();
        for (SysMenu sysMenu : list2) {
            SysMenuDto sysMenuDto2 = new SysMenuDto();
            BeanUtils.copyProperties(sysMenu, sysMenuDto2);  //拷贝数据

            /*找到每一个二级列表中对应的三级列表内容，并添加进去*/
            //二级列表中包含了三级列表
            Long id = sysMenu.getId();
            LambdaQueryWrapper<SysMenu> lqw2contain3 = new LambdaQueryWrapper<>();
            lqw2contain3.in(SysMenu::getPid, id);
            //每个三级列表的pid都与二级列表的id相同
            List<SysMenu> list = this.list(lqw2contain3);

            //为保持数据类型一致，把上面符合二级列表的三级列表数据重新放入一个集合中
            List<SysMenuDto> list2contain3 = new ArrayList<>();
            for (SysMenu menu : list) {
                SysMenuDto sysMenuDto = new SysMenuDto();
                BeanUtils.copyProperties(menu, sysMenuDto);
                list2contain3.add(sysMenuDto);
            }
            //为每一个二级列表的“列表、添加、更新、删除”添加进去
            sysMenuDto2.setChildren(list2contain3);

            sysMenuDtos2.add(sysMenuDto2);    //二级列表内容集合
        }

        //所有列表数据集合
        ArrayList<SysMenuDto> sysMenuDtos = new ArrayList<>();
        //将一级列表放进去
        LambdaQueryWrapper<SysMenu> lqw1 = new LambdaQueryWrapper<>();
        lqw1.like(SysMenu::getPath, "_");        //一级列表判断条件
        lqw1.notLike(SysMenu::getComponent, "/");//一级列表判断条件
        List<SysMenu> list1 = this.list(lqw1);

        for (SysMenu sysMenu : list1) {
            SysMenuDto sysMenuDto1 = new SysMenuDto();
            BeanUtils.copyProperties(sysMenu, sysMenuDto1);  //复制数据
            /*将二级列表与一级列表的对应先找到*/
            //根据一级的ID对应二级的PID完成一级对应二级的工作
            Long id1 = sysMenu.getId();
            LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<>();
            lqw.eq(SysMenu::getPid, id1);  //以一级的ID对应二级的PID
            List<SysMenu> list = this.list(lqw);
            /*对找出来的数据与上面2contain3进行匹配，把2contain3的集合放进一级列表dto集合*/
            //保持数据类型一致，将上述数据重新装入一个集合中
            ArrayList<SysMenuDto> sysMenuDtos1 = new ArrayList<>();
            for (SysMenu menu : list) {
                Long id = menu.getId();
                for (SysMenuDto sysMenuDto : sysMenuDtos2) {
                    //找一个能识别对应二级列表的字段即可
                    if (id.equals(sysMenuDto.getId())) {
                        sysMenuDtos1.add(sysMenuDto);   //真正的一级列表下拥有正确的二级和三级列表
                        /*最后把集合放入一级列表的dto中*/
                        sysMenuDto1.setChildren(sysMenuDtos1);
                        break;  //找到就跳出当前循环
                    }
                }
            }
            //将最终制作好的放入集合中
            sysMenuDtos.add(sysMenuDto1);
        }
        return sysMenuDtos;
    }

    /*
     * 1.删除时注意是否有子集，有不能删，没有才能删
     * 2.系统默认数据不能被删除
     * 3.若有角色在使用权限，不能删
     * */
    @Override
    public R<String> delete(Long id) {
        /*判断要删除的是否为默认数据*/
        //定义集合保存默认数据的ID
        ArrayList<Long> defaultSysMenus = new ArrayList<>();
        Collections.addAll(defaultSysMenus, 1L, 2L, 41L, 49L, 51L, 95L,
                96L, 97L, 98L, 99L, 100L, 101L, 102L, 108L, 109L, 110L, 111L,
                112L, 115L, 124L, 125L, 126L, 127L, 128L, 129L, 130L, 131L, 132L,
                133L, 134L, 135L, 136L, 137L, 138L, 139L, 140L, 141L, 142L, 143L,
                144L, 145L, 146L, 147L, 148L, 149L, 150L, 151L, 152L, 153L, 154L,
                155L, 156L, 157L, 158L, 159L, 160L, 161L, 162L, 163L, 164L, 165L,
                166L, 167L);
        for (Long menuId : defaultSysMenus) {
            if (id.equals(menuId)){
                return R.error("系统默认数据，不允许删除", 10000);
            }
        }

        /*判断要删除的是否存在子级*/
        LambdaQueryWrapper<SysMenu> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysMenu::getPid, id);    //某一项存在父级编号，说明它就是子级
        List<SysMenu> list = this.list(lqw);
        //存在子级就不删除
        if (list.size()>0){
            return R.error("存在子级，不允许删除！", 1000);
        }

        /*判断当前菜单是否存在角色使用*/
        LambdaQueryWrapper<SysRoleMenu> lqw1 = new LambdaQueryWrapper<>();
        lqw1.eq(SysRoleMenu::getMenuId, id);     //只要有一个存在就说明有角色在使用当前菜单(权限)
        List<SysRoleMenu> list1 = sysRoleMenuService.list(lqw1);
        if (list1.size()>0){
            //存在角色使用菜单，不能删
            return R.error("当前菜单正在被使用，不允许删除！", 1000);
        }

        //否则就可以删除
        this.removeById(id);
        return R.success("删除成功");
    }

}
